/**
 * 
 */
package constrain;

import java.util.HashMap;
import java.util.List;
import java.util.Random;

import gen.Table;

import org.apache.ibatis.session.SqlSession;

import sources.ISource;

/**
 * @author Kyniek
 *
 */
public class Constraint
{	
	String code;
	
	//parametry będą potrzebne do odzyskiwania informacji np na temat kluczy obcych.
	String params[];
	
	ConstraintType type;
	
	private DataDistribution distribution = DataDistribution.NATURAL;
	
	private Random rndGen = new Random(  (int)(Integer.MAX_VALUE * Math.random())  );
	
	
	public Constraint(ConstraintType type)
	{		
		this.type = type;
		code = type.getCode();
	}
	
	
	public Constraint(ConstraintType type, String... params)
	{
		type.setParams(params);
		this.params = params;
		this.type = type;
		code = type.getCode();		
	}
	
	
	public void executeConstrint(Table parent, ISource src, SqlSession session )
	{
		if(type == ConstraintType.FOREIGN_KEY)
		{
			//" REFERENCES " + args[0] + "(" + args[1] + ")" ;
			//tab , col
			
			String tab = parent.getName();//nazwa tabeli w której się wypełnia klucze główne
			String col = src.getName();
			String srcFKname = params[1];//nazwa kolumny klucza
			String srcFKtabName = params[0];
			//pobieranie tabeli źródłowej
			Table srcFK = parent.getSchema().getTable(srcFKtabName);
			//klucze z tabeli źródłowej
			List srcIDs = srcFK.selIDS(session);
			switch (distribution)
			{
				case NATURAL :
					//należy pobrać z tabeli źródłowej wartości ID i przypisać je do FK				

					System.out.println("debug : " + srcFKtabName + " : " + srcFK);										
					//gdy mam już listę id : list<object> ...
					//tabela powinna udostępniać metodę batchUpdate (colName - isource??, list_val)
					parent.batchUpdate(src, srcIDs, session);
					
					break;
				case RANDOM :
					//wybrać listę ID z tabeli
					//przydatna metoda : update each : wybranie ID z tabeli docelowej
					
					List ids = parent.selIDS(session);
					HashMap<String, Object> params = new HashMap<String, Object>();
					for(Object obID : ids)
					{
						//update ${tab} SET ${col} = #{val} WHERE {col2} = #{val2}
						params.put("tab", parent.getName());
						params.put("col", src.getName());
						params.put("val",   srcIDs.get( rndGen.nextInt(srcIDs.size())  )   );
						params.put("col2", parent.getPK().getName());
						params.put("val2", obID);
						session.update("update_where", params);
					}					
					break;
				case SQL :					
					if(this.params.length > 2 && this.params[2] != null)
					{
						if(this.params[2].toLowerCase().contains("${tab}"))
						{
							this.params[2] = this.params[2].replace("${tab}", parent.getName());
						}
						if(this.params[2].toLowerCase().contains("${col}"))
						{
							this.params[2] = this.params[2].replace("${col}", src.getName());
						}
						
						session.update("cmd", this.params[2]);
						//System.out.println(this.params[2]);
					}
					break;
				case BY_VAL :
					//update tab2 set fk=(select id from tab1 where tab2.val2 = tab1.val1)
					//tab2 => parent.getName()
					//fk => src.getName()
					//id => srcFK.getPK()
					//val2 => this.params[2]
					//val1 => this.params[3] - if exists, else this.params[2]
					//jeśli this.params[2] jest NULL to należy wyszukać wspólne kolumny
					
					break;
			}
		}
	}
	

	public String getCode()
	{
		return code;
	}

	public void setCode(String code)
	{
		this.code = code;
	}

	public ConstraintType getType()
	{
		return type;
	}

	public void setType(ConstraintType type)
	{
		this.type = type;
	}

	public String[] getParams()
	{
		return params;
	}

	public void setParams(String[] params)
	{
		this.params = params;
	}

	public DataDistribution getDistribution()
	{
		return distribution;
	}

	public void setDistribution(DataDistribution distribution)
	{
		this.distribution = distribution;
	}
	

}
